// Copyright 2020 Apulis Technology Inc. All rights reserved.

package storage

import (
	"fmt"
	"github.com/apulis/sdk/go-utils/storage/comm"
	"github.com/apulis/sdk/go-utils/storage/file"
	"github.com/apulis/sdk/go-utils/storage/s3"
	"io"
	"os"
)

var MethodBackendMap = map[string]Method{
	"FILE": &file.MethodBackendFile{},
	"S3":   &s3.MethodBackendS3{},
}

type Storage struct {
	Schema  string
	Err     error
	Handler Method
}

func New(schemaType string) (*Storage, error) {
	s := &Storage{
		Schema: "",
		Err:    nil,
	}

	_, ok := MethodBackendMap[schemaType]
	if !ok {
		return nil, fmt.Errorf("unknow schema = [%s]", schemaType)
	}

	s.Handler = MethodBackendMap[schemaType]
	return s, nil
}

// interface for storage
type Method interface {
	// 初始化
	Init(cfg comm.HandlerCfg) error
	/*
	 * @Desc  store file from local to destination;
	 *        destination may be local file or S3 on aws due to dst schema
	 * @Param localFilePath 本地文件路径
	 * @Param dst           存储目的地（本地文件、S3、etc.）, dst必须是带schema的格式
	 * @Param perm          目标文件的权限
	 */
	StoreFile(localFilePath string, dst string, perm os.FileMode) error
	/*
	 * @Desc  获取文件到本地，从src获取到本地dst; src必须是带schema格式
	 * @Param src 源文件
	 * @Param dstLocalPath 目标文件，本地文件
	 * @Param perm 目标文件权限
	 */
	GetFile(src string, dstLocalPath string, perm os.FileMode) error
	/*
	 * @Desc  打开文件，src必须是带schema格式，注意调用方拷贝完需要自行调用Close释放资源
	 * @Param src 源文件
	 */
	OpenFile(src string) (io.ReadCloser, error)
	/*
	 * @Desc  移动文件，从src移动到dst; src, dst必须是带schema格式
	 * @Param src 源文件
	 * @Param dst 目标文件
	 */
	MoveFile(src string, dst string) error
	/*
	 * @Desc  拷贝文件，从src拷贝到dst; src, dst必须是带schema格式
	 * @Param src 源文件
	 * @Param dst 目标文件
	 */
	CopyFile(src string, dst string) error
	/*
	 * @Desc  删除文件，dst必须是带schema格式
	 * @Param dst 目标文件
	 */
	DeleteFile(dst string) error
	/*
	 * @Desc  拷贝文件夹，从src拷贝到dst; src, dst必须是带schema格式
	 * @Param srcDir 源文件夹
	 * @Param dstDir 目标文件夹
	 */
	CopyDir(srcDir string, dstDir string) error
	/*
	 * @Desc  拷贝本地文件夹到dst; dst必须是带schema格式
	 * @Param srcDirLocal 本地源文件夹
	 * @Param dstDir 目标文件夹
	 */
	CopyFromLocalDir(srcDirLocal string, dstDir string) error
	/*
	 * @Desc  拷贝src文件夹到本地dst; src必须是带schema格式
	 * @Param srcDir 源文件夹
	 * @Param dstDirLocal 本地目标文件夹
	 */
	CopyFromRemoteDir(srcDir string, dstDirLocal string) error
	/*
	 * @Desc  移动文件夹，从src移动到dst; src, dst必须是带schema格式
	 * @Param srcDir 源文件夹
	 * @Param dstDir 目标文件夹
	 */
	MoveDir(srcDir string, dstDir string) error
	/*
	 * @Desc  移动本地文件夹到dst; dst必须是带schema格式
	 * @Param srcDirLocal 本地源文件夹
	 * @Param dstDir 目标文件夹
	 */
	MoveFromLocalDir(srcDirLocal string, dstDir string) error
	/*
	 * @Desc  移动src文件夹到本地dst; src必须是带schema格式
	 * @Param srcDir 源文件夹
	 * @Param dstDirLocal 本地目标文件夹
	 */
	MoveFromRemoteDir(srcDir string, dstDirLocal string) error
	/*
	 * @Desc  删除目录
	 * @Param srcDir 需要删除的目录，必须是带schema格式
	 * @Param force  true: 强制删除目录内的内容 false: 只删除目录本身，如内有文件则报错
	 */
	DeleteDir(dstDir string, force bool) error
	/*
	 * @Desc  创建目录
	 * @Param dst 需要删除的目录，必须是带schema格式
	 */
	Mkdir(dstDir string) error
}
